package com.lancer.dynamic.thread.pool;

import com.lancer.dynamic.thread.pool.config.ThreadPoolConfig;
import com.lancer.dynamic.thread.pool.domain.LancerQueue;
import com.lancer.dynamic.thread.pool.lancerenum.RejectEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;

import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

import static com.lancer.dynamic.thread.pool.domain.TheadPoolMap.POOL_CONFIG_MAP;
import static com.lancer.dynamic.thread.pool.domain.TheadPoolMap.POOL_EXECUTOR_MAP;

@Slf4j
public class ThreadPoolManage implements DisposableBean {


    public ThreadPoolManage(ThreadPoolConfig poolConfig) {
        addOrUpdateThreadPool(poolConfig);
    }

    /**
     * 添加或更新线程池
     *
     * @param poolConfig 池配置
     */
    public void addOrUpdateThreadPool(ThreadPoolConfig poolConfig) {
        RejectEnum rejectEnum = poolConfig.getRejectEnum();
        int corePoolSize = poolConfig.getCorePoolSize();
        int maxPoolSize = poolConfig.getMaxPoolSize();
        String poolName = poolConfig.getPoolName();
        int queueCapacity = poolConfig.getQueueCapacity();
        TimeUnit unit = poolConfig.getUnit();
        int keepAliveTime = poolConfig.getKeepAliveTime();
        try {
            // 判断线程池是否已经存在，进行更新
            if (POOL_EXECUTOR_MAP.containsKey(poolName)) {
                LancerExecutor threadPoolExecutor = POOL_EXECUTOR_MAP.get(poolName);
                POOL_CONFIG_MAP.put(poolName, poolConfig);
                threadPoolExecutor.setPoolName(poolName);
                threadPoolExecutor.setCorePoolSize(corePoolSize);
                threadPoolExecutor.setMaximumPoolSize(maxPoolSize);
                threadPoolExecutor.setKeepAliveTime(keepAliveTime, unit);
                threadPoolExecutor.updateRejectedPolicy(rejectEnum);
                BlockingQueue<Runnable> queue = threadPoolExecutor.getQueue();
                if (queue instanceof LancerQueue) {
                    ((LancerQueue<Runnable>) queue).setCapacity(queueCapacity);
                    log.info("动态更新队列容量成功，新容量为: {}", queueCapacity);
                } else {
                    log.warn("队列类型不支持动态扩容，跳过更新");
                }
                log.info("线程池已更新：{} {}", poolName, poolConfig);
            }
            // 新增
            else {
                LancerQueue<Runnable> queue = new LancerQueue<>(queueCapacity);
                // 创建线程池
                LancerExecutor threadPoolExecutor = new LancerExecutor(
                        corePoolSize,
                        maxPoolSize,
                        keepAliveTime,
                        unit,
                        queue,
                        rejectEnum,
                        poolName
                );
                // 根据拒绝策略枚举创建选择拒绝策略
                threadPoolExecutor.updateRejectedPolicy(rejectEnum);
                POOL_EXECUTOR_MAP.put(poolName, threadPoolExecutor);
                log.info("创建线程池成功：{} {}", poolName, poolConfig);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void destroy() throws Exception {
        // 销毁所有的线程池
        for (Map.Entry<String, LancerExecutor> entry : POOL_EXECUTOR_MAP.entrySet()) {
            String poolName = entry.getKey();
            LancerExecutor threadPoolExecutor = entry.getValue();
            threadPoolExecutor.shutdown();
            log.info("销毁线程池成功：{}", poolName);
        }
        // 保存销毁日志
    }

    public LancerExecutor getThreadPoolByName(String poolName) {
        if (!POOL_EXECUTOR_MAP.containsKey(poolName)) {
            log.warn("线程池不存在：{}", poolName);
            return null;
        }
        return POOL_EXECUTOR_MAP.get(poolName);
    }

    public void shutdownThreadPool(String poolName) {
        LancerExecutor threadPoolExecutor = getThreadPoolByName(poolName);
        if (threadPoolExecutor != null) {
            threadPoolExecutor.shutdown();
            log.info("销毁线程池成功：{}", poolName);
        }
    }

    public void forceShutdownThreadPool(String poolName) {
        LancerExecutor threadPoolExecutor = getThreadPoolByName(poolName);
        if (threadPoolExecutor != null) {
            threadPoolExecutor.shutdownNow();
            log.info("强制销毁线程池成功：{}", poolName);
        }
    }


}
